import * as React from 'react'
import { browser } from 'muka'
import { getClassName } from '../utils'

interface IProps {
    animateClass?: string
    height?: number | string
    autoplay?: boolean
    delay?: number
    infinite?: boolean
}

interface IState {
    animate: boolean
    x: number
}

export default class Carousel extends React.Component<IProps, IState> {
    public static defaultProps = {
        animateClass: 'transition',
        autoplay: true,
        delay: 3000
    }

    public state = {
        animate: false,
        x: 0
    }

    private startX: number = 0

    private moveX: number = 0

    private historyX: number = 0

    private index: number = 0

    private childrenLength: number = 0

    private timer: number

    public render(): JSX.Element {
        const { animateClass, children, height } = this.props
        const { animate, x } = this.state
        this.childrenLength = React.Children.count(children)
        return (
            <div className={getClassName('carousel')}>
                <div
                    className={getClassName('carousel_control', `${animate ? animateClass : ''}`)}
                    style={{ width: this.childrenLength * browser.width, transform: `translate(${x}px, 0)`, height }}
                    onTouchStart={this.handleStart}
                    onTouchMove={this.handleMove}
                    onTouchEnd={this.handleEnd}
                >
                    {
                        React.Children.map(children, (item: any, index: number) => {
                            return (
                                <div className={getClassName('carousel_item')} style={{ width: browser.width }} key={index}>{item}</div>
                            )
                        })
                    }
                </div>
            </div>
        )
    }

    public componentDidMount() {
        const { autoplay, delay } = this.props
        if (autoplay) {
            this.timer = setInterval(this.autoPlay, delay)
        }
    }

    public componentWillMount() {
        clearInterval(this.timer)
    }

    private autoPlay = () => {
        const { infinite } = this.props
        const index = this.index
        const maxNum = this.childrenLength - 1
        this.index = index === maxNum ? maxNum : index + 1
        if (!infinite && index === maxNum) {
            clearInterval(this.timer)
        } else if (infinite && index === maxNum) {
            this.index = 0
        }
        this.setState({
            x: -this.index * browser.width,
            animate: true
        })
    }

    private handleStart = (event: React.TouchEvent<HTMLDivElement>) => {
        const { x } = this.state
        const touch = event.targetTouches[0]
        this.historyX = x
        this.startX = touch.pageX
    }

    private handleMove = (event: React.TouchEvent<HTMLDivElement>) => {
        const touch = event.targetTouches[0]
        const x = touch.pageX - this.startX
        this.moveX = x
        this.setState({
            x: this.historyX + x,
            animate: false
        })
    }

    private handleEnd = () => {
        if (browser.width / 5 <= Math.abs(this.moveX)) {
            const index = this.index
            const maxNum = this.childrenLength - 1
            if (this.moveX < 0) {
                this.index = index === maxNum ? maxNum : index + 1
            } else {
                this.index = index === 0 ? 0 : index - 1
            }
        }
        this.setState({
            x: -this.index * browser.width,
            animate: true
        })
    }
}